package com.fay.mymiaosha.service.impl;

import com.fay.mymiaosha.dao.OrderDoMapper;
import com.fay.mymiaosha.dao.SequenceDoMapper;
import com.fay.mymiaosha.dataobject.OrderDo;
import com.fay.mymiaosha.dataobject.SequenceDo;
import com.fay.mymiaosha.exception.BizException;
import com.fay.mymiaosha.response.EmBizError;
import com.fay.mymiaosha.service.IItemService;
import com.fay.mymiaosha.service.IOrderService;
import com.fay.mymiaosha.service.IUserService;
import com.fay.mymiaosha.service.model.ItemModel;
import com.fay.mymiaosha.service.model.OrderModel;
import com.fay.mymiaosha.service.model.UserModel;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

/**
 * @Title:
 * @Description:
 * @Author Fay Wang
 * @Date 2022/3/18 18:55
 * @Version 1.0
 */
@Repository
public class OrderServiceImpl implements IOrderService {

    @Autowired
    private OrderDoMapper orderDoMapper;

    @Autowired
    private SequenceDoMapper sequenceDoMapper;

    @Autowired
    private IItemService itemService;

    @Autowired
    private IUserService userService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createOrder(Integer userId, Integer itemId, Integer promoId, Integer amount) throws BizException {
        // 1.校验下单状态，商品是否存在、用户是否合法、购买数量
        // 用户id已经校验   校验商品id  amount
        // 校验 就需要对比  先查
        ItemModel itemModel = itemService.getItemById(itemId);
        if (Objects.isNull(itemModel)) {
            throw new BizException(EmBizError.PARAMETER_VALIDATION_ERROR);
        }
        UserModel userModel = userService.getUserById(userId);
        if (Objects.isNull(userModel)) {
            throw new BizException(EmBizError.PARAMETER_VALIDATION_ERROR);
        }
        // 因为这不是按照Bean的方式传数据，所以没法用validator
        if (amount <= 0 || amount >= 99) {
            throw new BizException(EmBizError.PARAMETER_VALIDATION_ERROR);
        }

        // 校验是否为活动商品
        if (!Objects.isNull(promoId)) {
            // 之前先判断了商品Model存在，再判断商品Model的聚合中的活动Model,利用传参和数据库进行比较
            // id是否是商品模型中聚合的id一致（因为若该商品有秒杀活动，会将秒杀模型聚合进商品Model）
            if (promoId.intValue() != itemModel.getPromoModel().getId()) {
                throw  new BizException(EmBizError.PARAMETER_VALIDATION_ERROR,"活动信息不正确");
            } else if (itemModel.getPromoModel().getStatus() != 2) {
                // 只有当前在活动中，才能这样计算，否则认为是一场
                throw new BizException(EmBizError.PARAMETER_VALIDATION_ERROR, "秒杀不在进行中");
            }
        }

        // 2.落单减库存，支付减库存
        // 采用落单减库存，需要在商品服务中提供减库存的方法
        boolean result = itemService.decreaseStock(itemId, amount);
        // 下单数量大于库存量
        if (!result) {
            throw new BizException(EmBizError.STOCK_NOT_ENOUGH);
        }
        // 否则，扣减库存
        // 3.订单入库
        OrderModel orderModel = new OrderModel();
        orderModel.setAmount(amount);
        orderModel.setItemId(itemId);
        orderModel.setUserId(userId);
        // 如果有秒杀，下单价格是秒杀价格
        if (promoId != null) {
            orderModel.setItemPrice(itemModel.getPromoModel().getPromoItemPrice());
        } else {
            orderModel.setItemPrice(itemModel.getPrice());
        }
        orderModel.setOrderPrice(itemModel.getPrice().multiply(BigDecimal.valueOf(amount)));
        orderModel.setId(this.generateOrderNo());

        //convert orderModel to orderDo
        OrderDo orderDo = convertFromOrderModel(orderModel);
        // 保存订单
        orderDoMapper.insertSelective(orderDo);
        // 增加销量
        itemService.increaseSales(itemId, amount);
        // 4.返回前端
    }

    private OrderDo convertFromOrderModel(OrderModel orderModel) {
        if (Objects.isNull(orderModel)) {
            return null;
        }
        OrderDo orderDo = new OrderDo();
        BeanUtils.copyProperties(orderModel, orderDo);
        orderDo.setOrderPreice(orderModel.getOrderPrice().doubleValue());
        orderDo.setItemPrice(orderModel.getItemPrice().doubleValue());
        return orderDo;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public String generateOrderNo() {
        StringBuilder orderStr = new StringBuilder();
        // 1-8 time 9-14 unique num 15-16 db num
        LocalDateTime now = LocalDateTime.now();
        String nowDateStr = now.format(DateTimeFormatter.ISO_DATE).replace("-", "");
        orderStr.append(nowDateStr);

        int sequence = 0;
        SequenceDo sequenceDo = sequenceDoMapper.getSequenceByName("order_info");

        // get current_value
        sequence = sequenceDo.getCurrentValue();
        // generate new value, accumulate by step
        sequenceDo.setCurrentValue(sequenceDo.getCurrentValue() + sequenceDo.getStep());
        // update new current_value
        sequenceDoMapper.updateByPrimaryKeySelective(sequenceDo);

        // fill the mid-num, front blank digit with 0
        String sequenceStr = String.valueOf(sequence);
        for (int i = 0; i < 6 - sequenceStr.length(); i++) {
            orderStr.append(0);
        }

        orderStr.append(sequenceStr);
        orderStr.append("00");

        return orderStr.toString();
    }
}
